/* Copyright (c) 2025 Beijing Semidrive Technology Corporation
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/** *****************************************************************************************************
 *  \file     Pfu_Ip.h                                                                                  *
 *  \brief    This file contains interface header for PFU low level driver                              *
 *                                                                                                      *
 * <table>                                                                                              *
 * <tr><th>Date           <th>Version                                                                   *
 * <tr><td>2024/11/18     <td>1.0.0                                                                     *
 * </table>                                                                                             *
 *******************************************************************************************************/
#ifndef PFU_H
#define PFU_H

/********************************************************************************************************
 *                                      Include header files                                            *
 *******************************************************************************************************/
#include "lld_platform.h"

/**
 *
 * \defgroup PFU PFU Driver API
 *
 * The PFU Driver low level driver provides low level access to PFU peripheral
 *
 * \sa PFU_CFG
 * \sa PFU_API
 * \sa PFU_MACRO
 * \{
 */

/**
 *  \defgroup PFU_CFG PFU Configuration.
 *
 * This files defines PFU low level driver configuration structures
 *  \{
 */

/** \} */

/**
 *  \defgroup PFU_API PFU Api.
 *
 * This files defines PFU low level driver api
 *  \{
 */

/** \} */

/**
 *  \defgroup PFU_MACRO PFU macro.
 *
 * This files defines PFU low level driver macro
 *  \{
 */

/** \} */

/**
 *  \addtogroup PFU_MACRO PFU macro.
 *  \{
 */
/********************************************************************************************************
 *                                 Global Macro definition                                              *
 *******************************************************************************************************/
/**
 *  \name PFU Error Codes
 *
 *  Error codes returned by PFU functions
 *  \{
 */
#if defined (CFG_PLATFORM_MCAL)
/** \brief  ERROR Description:timeout */
#define PFU_E_TIMEOU (0x01U)
/** \brief  ERROR Description:Start or end address not 4K aligned */
#define PFU_E_ALIGNMENT (0x02U)
#elif defined (CFG_PLATFORM_SSDK)
/** \brief  ERROR Description:timeout */
# define PFU_E_TIMEOU (SDRV_STATUS_TIMEOUT)
/** \brief  ERROR Description:Start or end address not 4K aligned */
#define PFU_E_ALIGNMENT (SDRV_STATUS_INVALID_PARAM)
#else
#error "Undefined macros CFG_PLATFORM_MCAL or CFG_PLATFORM_SSDK"
#endif /** #if defined (CFG_PLATFORM_MCAL) */
/** \} */
/** \} */


/** \cond private macro definition */
/********************************************************************************************************
 *                                 Private Macro definition                                             *
 *******************************************************************************************************/
/** \brief  polling time */
#define PFU_POLLING_TIMEOUT (6000UL)
/** \brief  4K Alignment */
#define PFU_4K_ALIGNMENT (0xfffUL)
/** \endcond */

/**
 *  \addtogroup PFU_CFG PFU Configuration.
 *  \{
 */
/********************************************************************************************************
 *                                  Global Types definition                                             *
 *******************************************************************************************************/
/**
 *  \brief pfu region type
 */
typedef enum
{
    /** region 0 */
    PFU_REION0 = 0UL,
    /** region 1 */
    PFU_REION1,
    PFU_REGION_MAX
} Pfu_Ip_RegionType;

/**
 *  \brief pfu interrupt config
 */
typedef enum
{
    /** axi slave timeout */
    PFU_AXI_SLV_TIMEOUT = 0x01UL << 0UL,
    /** axi master timeout */
    PFU_AXI_MST_TIMEOUT = 0x01UL << 1UL,
    /** response error */
    PFU_RESP_ERROR = 0x01UL << 2UL,
    /* PRQA S 1535 1 */
} Pfu_Ip_InterruptType;

/**
 *  \brief pfu region config type
 */
typedef struct
{
    /** pfu start addr need 4K alignment */
    uint32_t startAddr;
    /** pfu end addr need 4K alignment */
    uint32_t endAddr;
    /** pfu need config region ID */
    Pfu_Ip_RegionType regionId;
} Pfu_Ip_RegionCfgType;

/**
 *  \brief pfu interrupt config
 */
typedef struct
{
    /** Whether to enable response error interrupt */
    bool responseErr;
    /** Whether to enable axi master timeout interrupt */
    bool axiMstTimeout;
    /** Whether to enable axi slave timeout interrupt */
    bool axiSlvTimeout;
} Pfu_Ip_InterruptCfgType;
/** \} */

/**
 *  \addtogroup PFU_API PFU Api.
 *  \{
 */
/********************************************************************************************************
 *                                  Global Function Declarations                                        *
 *******************************************************************************************************/
/** *****************************************************************************************************
 * \brief PFU bypass function.
 *
 * \verbatim
 * Syntax             : lld_status_t Pfu_Ip_Bypass(uint32_t base, bool bypassEn, uint32_t timeout)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - pfu base address
 *                      bypassEn - true : bypass
 *                                 false : pfu enable
 *                      timeout - timeout val.If timeout = 0 use the internal
 *                              PFU_POLLING_TIMEOUT macro as a timeout cnt
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : error code
 *
 * Description        : This interface requires the CPU's L2 interface to be idle
 *                      in order not to return a timeout error. There are two ways
 *                      to do this:
 *                      1. Open the cache to ensure that both the code segment and
 *                      the stack need to be placed in the cacheable.
 *                      2. Configure the corresponding CPU's PFU before the CPU kick.
 *                      Enable bypass function CPU will not prefetch, but the read data
 *                      will be put into PFU buff.
 * \endverbatim
 *******************************************************************************************************/
lld_status_t Pfu_Ip_Bypass(uint32_t base, bool bypassEn, uint32_t timeout);

/** *****************************************************************************************************
 * \brief Refresh region space function.
 *
 * \verbatim
 * Syntax             : void Pfu_Ip_Flush(uint32_t base)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - pfu base address
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : error code
 *
 * Description        : Mainly used when you need to refresh the region. If the internal
 *                      MEMORY is modified.
 *                      This interface requires the CPU's L2 interface to be idle
 *                      in order not to return a timeout error. There are two ways
 *                      to do this:
 *                      1. Open the cache to ensure that both the code segment and
 *                      the stack need to be placed in the cacheable.
 *                      2. Configure the corresponding CPU's PFU before the CPU kick.
 * \endverbatim
 *******************************************************************************************************/
void Pfu_Ip_Flush(uint32_t base);

/** *****************************************************************************************************
 * \brief prefetch en function.
 *
 * \verbatim
 * Syntax             : uint8_t Pfu_Ip_PrefetchEn(uint32_t base, bool prefetchEn)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - pfu base address
 *                      prefetchEn - prefetch en
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Turns off and on the CPU prefetch function.
 *                      You need to enable bypass to operate this interface.
 * \endverbatim
 *******************************************************************************************************/
void Pfu_Ip_PrefetchEn(uint32_t base, bool prefetchEn);

/** *****************************************************************************************************
 * \brief Configuring the Region Function Interface.
 *
 * \verbatim
 * Syntax             : lld_status_t Pfu_Ip_RegionConfig(uint32_t base,
 *                                               const Pfu_Ip_RegionCfgType *cfg)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - pfu base address
 *                      cfg - region config
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : error code
 *
 * Description        : Configuring the Region Function Interface.
 * \endverbatim
 *******************************************************************************************************/
lld_status_t Pfu_Ip_RegionConfig(uint32_t base, const Pfu_Ip_RegionCfgType *cfg);

/** *****************************************************************************************************
 * \brief Interrupt Configuration Function Interface.
 *
 * \verbatim
 * Syntax             : void Pfu_Ip_InterruptConfig(uint32_t base,
 *                                              const Pfu_Ip_InterruptCfgType *cfg)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - pfu base address
 *                      cfg - interrupt config
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : Interrupt Configuration Function Interface.
 * \endverbatim
 *******************************************************************************************************/
void Pfu_Ip_InterruptConfig(uint32_t base, const Pfu_Ip_InterruptCfgType *cfg);

/** *****************************************************************************************************
 * \brief Get Interrupt Status Function Interface.
 *
 * \verbatim
 * Syntax             : uint32_t Pfu_Ip_GetInterruptSta(uint32_t base)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - pfu base address
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : interrupt raw data
 *                      The meaning of the corresponding bit can be seen in the
 *                      type Pfu_Ip_InterruptType.
 *
 * Description        : Get Interrupt Status Function Interface.
 * \endverbatim
 *******************************************************************************************************/
uint32_t Pfu_Ip_GetInterruptSta(uint32_t base);

/** *****************************************************************************************************
 * \brief clear interrupt.
 *
 * \verbatim
 * Syntax             : void Pfu_Ip_InterruptClr(uint32_t base, uint32_t msk)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - pfu base address
 *                      msk - Can be one or more of the enumerated types Pfu_Ip_InterruptType.
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : clear interrupt.
 * \endverbatim
 *******************************************************************************************************/
void Pfu_Ip_InterruptClr(uint32_t base, uint32_t msk);

/** *****************************************************************************************************
 * \brief config axi master timeout
 *
 * \verbatim
 * Syntax             : void Pfu_Ip_AxiMstTimeoutCfg(uint32_t base, uint32_t timeout)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - pfu base address
 *                      timeout - timeout val(The formula is as follows: us = timeout /axi_clk)
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : config axi master timeout
 *                      The formula is as follows: us = timeout /axi_clk
 * \endverbatim
 *******************************************************************************************************/
void Pfu_Ip_AxiMstTimeoutCfg(uint32_t base, uint32_t timeout);

/** *****************************************************************************************************
 * \brief config axi master timeout
 *
 * \verbatim
 * Syntax             : void Pfu_Ip_AxiSlvTimeoutCfg(uint32_t base, uint32_t timeout)
 *
 * Service ID[hex]    : None
 *
 * Sync/Async         : Synchronous
 *
 * Reentrancy         : Non reentrant
 *
 * Parameters (in)    : base - pfu base address
 *                      timeout - timeout val(The formula is as follows: us = timeout /axi_clk)
 *
 * Parameters (inout) : None
 *
 * Parameters (out)   : None
 *
 * Return value       : None
 *
 * Description        : config axi master timeout
 *                      The formula is as follows: us = timeout /axi_clk
 * \endverbatim
 *******************************************************************************************************/
void Pfu_Ip_AxiSlvTimeoutCfg(uint32_t base, uint32_t timeout);
/** \} */
/** \} */

#endif /* PFU_H */
/* End of file */
